﻿/*---------------------------------------------------------------- 
// Copyright 2005-2016 My Tech. Co. Ltd. All Rights Reserved.
// 版权所有。  
// 
// 文件名： CradleHeadBll
// 文件功能描述： 
// 
//  
// 创建标识： wx2016/11/11 16:38:35
// 
// 修改标识： 
// 修改描述： 
//----------------------------------------------------------------*/

using MyBLL.Dto;
using MyMiddleware;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyBLL
{
    public class PTZBll
    {
        private static Device device;

        //线程安全的接收消息队列
        public static ConcurrentQueue<List<PTZInfo>> getPTZQueue;

        public static string InterferenceStr = "00000000";

        //向上
        private static byte[] comandUp = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X01, 0X00, 0x00, 0x00 };
        //向下
        private static byte[] comandDown = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X02, 0X00, 0x00, 0x00 };
        //向左
        private static byte[] comandLeft = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X03, 0X00, 0x00, 0x00 };
        //向右
        private static byte[] comandRight = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X04, 0X00, 0x00, 0x00 };
        //回到零点
        private static byte[] comandZero = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X11, 0X00, 0x00, 0x00 };
        //开启防御
        private static byte[] comandInterference = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X15, 0X01, 0x00, 0x00, 0x00 };
        //停止防御
        private static byte[] comandStopInterference = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X16, 0X01, 0x00, 0x00, 0x00 };
        //按方位角定位
        private static byte[] comandOrientation = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X17, 0X04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        //获取云台方位数据
        private static byte[] comandGetState = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0X20, 0X00, 0X00, 0x00 };
        //停止云台
        public static byte[] comandStop = new byte[] { 0XA5, 0X5A, 0x01, 0X20, 0x05, 0X00, 0X00, 0x00 };

        /// <summary>
        /// 获取校验和，出去命令头两个字节的累加和计算
        /// </summary>
        /// <param name="comand">指令</param>
        /// <returns></returns>
        private static byte[] checkComand(byte[] comand)
        {
            byte checksum = 0;
            for (int i = 2; i < comand.Length - 1; i++)
            {
                checksum += comand[i];
            }
            comand[comand.Length - 1] = checksum;
            return comand;
        }

        /// <summary>
        /// 获取向上指令
        /// </summary>
        /// <returns></returns>
        private static byte[] GetCmdUp()
        {
            return checkComand(comandUp);
        }

        /// <summary>
        /// 获取向下指令
        /// </summary>
        /// <returns></returns>
        private static byte[] GetCmdDown()
        {
            return checkComand(comandDown);
        }

        /// <summary>
        /// 获取向左指令
        /// </summary>
        /// <returns></returns>
        private static byte[] GetCmdLeft()
        {
            return checkComand(comandLeft);
        }

        /// <summary>
        /// 获取向右指令
        /// </summary>
        /// <returns></returns>
        private static byte[] GetCmdRight()
        {
            return checkComand(comandRight);
        }

        /// <summary>
        /// 获取按方位角定位指令
        /// </summary>
        /// <returns></returns>
        private static byte[] GetCmdOrientation(float a, float b)
        {
            //组包
            //如果a为负数
            if(a<0)
            {
                //如果a带小数点
                if(a.ToString().IndexOf('.')>0)
                {
                    int num = 128 + Convert.ToUInt16(a.ToString().Split('.')[1]);
                    int num2 = Convert.ToInt16(a.ToString().Split('.')[0]) * -1;
                    comandOrientation[7] = Convert.ToByte(num);
                    comandOrientation[8] = Convert.ToByte(num2);
                }
                else
                {
                    int num = 128 ;
                    int num2 = Convert.ToInt16(a) * -1;
                    comandOrientation[7] = Convert.ToByte(num);
                    comandOrientation[8] = Convert.ToByte(num2);
                }
            }
            else
            {
                if (a.ToString().IndexOf('.') > 0)
                {
                    int num = Convert.ToUInt16(a.ToString().Split('.')[1]);
                    int num2 = Convert.ToUInt16(a.ToString().Split('.')[0]);
                    comandOrientation[7] = Convert.ToByte(num);
                    comandOrientation[8] = Convert.ToByte(num2);
                }
                else
                {
                    int num = 0;
                    int num2 = Convert.ToUInt16(a);
                    comandOrientation[7] = Convert.ToByte(num);
                    comandOrientation[8] = Convert.ToByte(num2);
                }
            }

            if (b < 0)
            {
                //如果b带小数点
                if (b.ToString().IndexOf('.') > 0)
                {
                    int num = 128 + Convert.ToUInt16(b.ToString().Split('.')[1]);
                    int num2 = Convert.ToInt16(b.ToString().Split('.')[0])*-1;
                    comandOrientation[9] = Convert.ToByte(num);
                    comandOrientation[10] = Convert.ToByte(num2);
                }
                else
                {
                    int num = 128;
                    int num2 = Convert.ToInt16(b) * -1;
                    comandOrientation[9] = Convert.ToByte(num);
                    comandOrientation[10] = Convert.ToByte(num2);
                }
            }
            else
            {
                if (b.ToString().IndexOf('.') > 0)
                {
                    int num = Convert.ToUInt16(b.ToString().Split('.')[1]);
                    int num2 = Convert.ToUInt16(b.ToString().Split('.')[0]);
                    comandOrientation[9] = Convert.ToByte(num);
                    comandOrientation[10] = Convert.ToByte(num2);
                }
                else
                {
                    int num = 0;
                    int num2 = Convert.ToUInt16(b);
                    comandOrientation[9] = Convert.ToByte(num);
                    comandOrientation[10] = Convert.ToByte(num2);
                }
            }
            //生成校验位
            return checkComand(comandOrientation);
        }



        private static byte[] GetCmdStopIntf()
        {
            byte temp = Convert.ToByte(InterferenceStr, 2);
            comandInterference[7] = temp;
            return checkComand(comandInterference);
        }

        private static byte[] GetCmdGetState()
        {
            return checkComand(comandGetState);
        }

        private static byte[] GetCmdZero()
        {
            return checkComand(comandZero);
        }

        private static byte[] GetCmdStartIntf()
        {
            byte temp = Convert.ToByte(InterferenceStr, 2);
            comandInterference[7] = temp;
            return checkComand(comandInterference);
        }

        private static byte[] GetCmdStop()
        {
           
            return checkComand(comandStop);
        }

        /// <summary>
        /// 发送指令
        /// </summary>
        /// <param name="cmd">指令类型</param>
        /// <param name="device">设备</param>
        /// <returns></returns>
        public static bool SendCmd(CradleHeadCmd cmd, Device device)
        {
            //if(device.OnGetData==null)
            device.OnGetData += device_OnGetData;
            byte[] cmdTemp = null;
            switch (cmd)
            {
                case CradleHeadCmd.Up:
                    cmdTemp = GetCmdUp();
                    break;
                case CradleHeadCmd.Down:
                    cmdTemp = GetCmdDown();
                    break;
                case CradleHeadCmd.Left:
                    cmdTemp = GetCmdLeft();
                    break;
                case CradleHeadCmd.Right:
                    cmdTemp = GetCmdRight();
                    break;
                case CradleHeadCmd.Orientation:
                    //cmdTemp = GetCmdOrientation();
                    break;
                case CradleHeadCmd.Stop:
                    cmdTemp = GetCmdStop();
                    break;
                case CradleHeadCmd.StartIntf:
                    cmdTemp = GetCmdStartIntf();
                    break;
                case CradleHeadCmd.StopIntf:
                    cmdTemp = GetCmdStopIntf();
                    break;
                case CradleHeadCmd.Zero:
                    cmdTemp = GetCmdZero();
                    break;
                case CradleHeadCmd.GetState:
                    cmdTemp = GetCmdGetState();
                    break;
                default:
                    break;
            }
            bool sendBl = false;
            try
            {
                sendBl = device.GetDataByCommand(cmdTemp);
            }
            catch (Exception)
            {

            }

            return sendBl;
        }

        /// <summary>
        /// 发送指令
        /// </summary>
        /// <param name="cmd">指令类型</param>
        /// <param name="device">设备</param>
        /// <returns></returns>
        public static bool SendCmd(CradleHeadCmd cmd,float a,float b, Device device)
        {
            //if(device.OnGetData==null)
            device.OnGetData += device_OnGetData;
            byte[] cmdTemp = null;
            switch (cmd)
            {
                case CradleHeadCmd.Orientation:
                    cmdTemp = GetCmdOrientation(a,b);
                    break;
                default:
                    break;
            }
            bool sendBl = false;
            try
            {
                sendBl = device.GetDataByCommand(cmdTemp);
            }
            catch (Exception)
            {

            }

            return sendBl;
        }

        static void device_OnGetData(object sender, DataEventArgs args)
        {
            byte[] data = args.MyData;
            List<PTZInfo> ptzInfos = unPack(data, (Device)sender);
            getPTZQueue.Enqueue(ptzInfos);
        }

        private static List<byte> buffer1 = new List<byte>(10240);//
        static List<PTZInfo> unPack(byte[] data, Device device)
        {
            List<PTZInfo> ptzInfoList = new List<PTZInfo>();
            
            buffer1.AddRange(data);//1.缓存数据
            int bufferLength = 0;
            while (buffer1.Count > 0)
            {
                byte[] bufProc = null;//声明一个临时数组存储当前来的数据
                byte[] bufTemp = null;//声明一个临时数组存储剩下的数据
                //找到帧头，去掉帧头前面
                for (int i = 0; i < buffer1.Count; i++)
                {
                    //找到帧头
                    if (buffer1[i].Equals(0xA5) && buffer1[i + 1].Equals(0x5A))
                    {
                        bufferLength = BitConverter.ToInt16(buffer1.Skip(5 + i).Take(2).ToArray(), 0) + 7;
                        bufProc = buffer1.Skip(i).Take(bufferLength).ToArray();
                        bufTemp = buffer1.Skip(i + bufferLength).Take(buffer1.Count - i - bufferLength).ToArray();
                        break;
                    }
                }
                buffer1.Clear();
                //云台未做数据清楚，所以剩余数据为垃圾数据，不用作为下个数据包的开头
                //if (bufTemp != null)
                //    buffer1.AddRange(bufTemp);
                if (bufProc != null)
                {
                    PTZInfo ptzInfo = Distribution(bufProc);
                    if(ptzInfo!=null)
                        ptzInfoList.Add(ptzInfo);
                }

            }

            return ptzInfoList;
        }

        public static PTZInfo PtzInfo1 = new PTZInfo();
        private static PTZInfo Distribution(byte[] bufProc)
        {
            if (bufProc == null)
                return null;
            PTZInfo ptzInfo = new PTZInfo();
            byte command = bufProc[4];
            ptzInfo.GetCommand = command;
            if (command.Equals(0xA2))
            {
                byte src = bufProc[2];
                if (src.Equals(0x01))
                    return null;

                byte sendCommand = bufProc[7];
                ptzInfo.SendCommand = sendCommand;
                if(sendCommand.Equals(0x20))
                {
                    int dataLength = BitConverter.ToInt16(bufProc.Skip(5).Take(2).ToArray(), 0);
                    if(dataLength != 6)
                        return null;
                    //0和1标志后三位，分为bit2 GPS、bit1 2.4G、bit0 5.8G的干扰停止和干扰中的状态
                    string state = bufProc[8].ToString();
                    ptzInfo.State = state;
                    float pointX1 =  (float)bufProc[9];
                    float pointX2 = (float)bufProc[10];
                    string pointXStr = "";
                    if (pointX1 >= 128)
                        pointXStr = (pointX2 + (pointX1 - 128) * 0.1f) * -1 + "";
                    else
                    {
                        pointXStr = pointX2 + pointX1 * 0.1f + "";
                    }
                    float pointY1 = (float)bufProc[11];
                    float pointY2 = (float)bufProc[12];
                    string pointYStr = "";
                    if (pointY1 >= 128)
                        pointYStr = (pointY2 + (pointY1 - 128) * 0.1f) * -1 + "";
                    else
                    {
                        pointYStr = pointY2 + pointY1 * 0.1f + "";
                    }
                    ptzInfo.PointX = pointXStr;
                    ptzInfo.PointY = pointYStr;
                    PtzInfo1 = ptzInfo;
                }
                else
                {
                    byte result = bufProc[8];
                    if (result.Equals(0x0F))
                    {
                        ptzInfo.Result = true;
                    }
                    else if (result.Equals(0xF0))
                    {
                        ptzInfo.Result = false;
                    }
                }
            }

            //ShowPointX();
            //ShowPointY();
            return ptzInfo;
        }

        //Lable
        //public static SetShowXControl(Lable)
        //{

        //}


        //public static void SetShowXControl(global::System.Windows.Controls.Label lb_PointX)
        //{
        //    throw new NotImplementedException();
        //}
    }
    public enum CradleHeadCmd
    {
        /// <summary>
        /// 向上
        /// </summary>
        Up,
        /// <summary>
        /// 向下
        /// </summary>
        Down,
        /// <summary>
        /// 向左
        /// </summary>
        Left,
        /// <summary>
        /// 向右
        /// </summary>
        Right,
        /// <summary>
        /// 按方位定位
        /// </summary>
        Orientation,
        /// <summary>
        /// 回到零点
        /// </summary>
        Zero,
        /// <summary>
        /// 停止转动
        /// </summary>
        Stop,
        /// <summary>
        /// 开始防御
        /// </summary>
        StartIntf,
        /// <summary>
        /// 停止防御
        /// </summary>
        StopIntf,
        /// <summary>
        /// 获取状态
        /// </summary>
        GetState
    }

}
